package com.zy.函数式编程.高阶函数

object Test {


  def main(args: Array[String]): Unit = {

    // 1. 函数可以作为值进行传递

    def function1(): Unit = println("函数被调用了!")

    // 在函数名后加下划线，表示指这个函数本身而不是运行函数
    val fun1 = function1 _
    // 或者指定参数的返回值类型
    val fun2: () => Unit = function1
    println(fun1) // 函数引用地址
    fun1()
    println(fun2) // 函数引用地址
    fun2()

    println("=========================================")

    // 2. 函数作为函数参数作为参数
    def function2(op: (Int, Int) => Int, a: Int, b: Int): Int = op(a, b)

    def add(a: Int, b: Int): Int = a + b

    println(function2(add, 1, 2))
    val fun3 = add _
    println(function2(fun3, 1, 2))
    println(function2(_ + _, 1, 2)) // 传入匿名函数

    println("=========================================")

    // 3. 函数作为返回值传递
    def function4(): Int => Unit = {
      def function5(a: Int): Unit = println(s"函数被调用:${a}")

      function5
    }

    println(function4()) // 返回函数地址并打印
    function4()(25) // 调用函数返回的函数

    println("=========================================")

    // 案例：实现一个map操作
    def arrayOperation(array: Array[Int], op: Int => Int) = for (arr <- array) yield op(arr)

    val array: Array[Int] = Array(1, 3, 51, 89, 100)

    // 数组所有元素加一
    val res1: Array[Int] = arrayOperation(array, _ + 1)
    println(res1.mkString(","))

    val res2: Array[Int] = arrayOperation(array, _ * 3)
    println(res2.mkString(","))


    println("=========================================")

    // 练习
    def function5(i: Int): String => (Char => Boolean) = {
      def function6(s: String): Char => Boolean = {
        def function7(c: Char): Boolean = {
          if (i == 0 && s.equals("") && c == '0') false else true
        }

        function7
      }

      function6
    }

    println(function5(0)("")('0'))
    println(function5(0)("")('a'))
    println(function5(0)("hello")('0'))

    // 练习的简化  因为在最外层中已经限定了函数的返回值类型，因此在内部定义时可以不写函数入参和返回值类型
    def fun5(i: Int): String => (Char => Boolean) = {
      s => c => if (i == 0 && s.equals("") && c == '0') false else true
    }

    // 练习题的另一种简化方式：柯里化
    def function8(i: Int)(s:String)(c:Char):Boolean = if (i == 0 && s.equals("") && c == '0') false else true
    println(function8(0)("")('0'))
    println(function8(0)("")('a'))
    println(function8(0)("hello")('0'))

  }
}
